/*
 * XXX
 */

package edu.uhcl.csci4838.group3.view;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import edu.uhcl.csci4838.group3.R;
import edu.uhcl.csci4838.group3.database.BackpackEduDatabaseHelper;
import edu.uhcl.csci4838.group3.database.BackpackEduDatabaseHelper.CursorHoliday;
import edu.uhcl.csci4838.group3.database.BackpackEduDatabaseHelper.CursorSemester;
import edu.uhcl.csci4838.group3.database.info.Holiday;
import edu.uhcl.csci4838.group3.database.info.Semester;
import edu.uhcl.csci4838.group3.view.help.HelpActivity;
import edu.uhcl.csci4838.group3.widget.DateButton;
import edu.uhcl.csci4838.group3.widget.StateRelativeLayout;

/**
 * XXX
 * 
 * @author Chris Waguespack
 */
public class EditSemesterActivity extends Activity {
	
	/**
	 * XXX
	 * 
	 * @author Chris Waguespack
	 */
	private class CustomDateSetListener implements
			DatePickerDialog.OnDateSetListener {
		
		/**
		 * XXX
		 */
		private final DateButton dateButton;
		
		/**
		 * XXX
		 * 
		 * @param dateButton
		 *            XXX
		 */
		public CustomDateSetListener(final DateButton dateButton) {
			this.dateButton = dateButton;
		}
		
		/**
		 * XXX
		 * 
		 * @param view
		 *            XXX
		 * @param year
		 *            XXX
		 * @param monthOfYear
		 *            XXX
		 * @param dayOfMonth
		 *            XXX
		 */
		/* 
		 * (non-Javadoc)
		 * 
		 * @see android.app.DatePickerDialog.OnDateSetListener#onDateSet(android.widget.DatePicker, int, int, int)
		 */
		@Override
		public void onDateSet(final DatePicker view,
				final int year,
				final int monthOfYear,
				final int dayOfMonth) {
			this.dateButton.setYear(year);
			this.dateButton.setMonth(monthOfYear);
			this.dateButton.setDay(dayOfMonth);
		}
	}
	
	/**
	 * XXX
	 */
	private static final int DATE_DIALOG_ID = 0;
	
	/**
	 * The database helper object.
	 */
	private static BackpackEduDatabaseHelper dbHelper;
	
	/**
	 * The semester cursor used to populate this form.
	 */
	private CursorSemester semesterCursor;
	
	/**
	 * A list of deleted holiday ids.
	 */
	private List<Long> deletedHolidayIds;
	
	private static EditText inputSemesterName;
	private static Button btnAddHoliday;
	private static LinearLayout layoutHolidays;
	
	/**
	 * XXX
	 * 
	 * @param view
	 *            XXX
	 */
	public void addHolidayListItem(final View view) {
		this.getLayoutInflater()
				.inflate(R.layout.holidayadd,
						EditSemesterActivity.layoutHolidays);
	}
	
	/**
	 * XXX
	 * 
	 * @param view
	 *            XXX
	 */
	public void formCancel(final View view) {
		this.finish();
	}
	
	/**
	 * XXX
	 * 
	 * @param view
	 *            XXX
	 */
	public void formDone(final View view) {
		if (this.semesterCursor == null) {
			// Add
			final String semesterName = EditSemesterActivity.inputSemesterName.getText()
					.toString()
					.trim();
			if (semesterName.length() == 0) {
				// Empty string
				Toast.makeText(this,
						"The semester name cannot be empty!",
						Toast.LENGTH_LONG)
						.show();
				return;
			}
			
			// Check for existing semester
			final ContentValues criteria = new ContentValues(1);
			criteria.put(Semester.NAME,
					semesterName);
			final CursorSemester newSemesterCursor = EditSemesterActivity.dbHelper.getSemester(criteria,
					null,
					true);
			if (newSemesterCursor.getCount() != 0) {
				// The semester name already exists
				Toast.makeText(this,
						"A semester with that name already exists!",
						Toast.LENGTH_LONG)
						.show();
				return;
			}
			newSemesterCursor.close();
			
			// Holidays
			final List<edu.uhcl.csci4838.group3.dto.Holiday> holidays = new ArrayList<edu.uhcl.csci4838.group3.dto.Holiday>(EditSemesterActivity.layoutHolidays.getChildCount());
			for (int i = 0; i < EditSemesterActivity.layoutHolidays.getChildCount(); ++i) {
				final View child = EditSemesterActivity.layoutHolidays.getChildAt(i);
				if (child.getId() == R.id.holidayadd) {
					final String holidayName = ((EditText) child.findViewById(R.id.editText_setHolidayName)).getText()
							.toString()
							.trim();
					if (holidayName.length() == 0) {
						// Empty string
						Toast.makeText(this,
								"A holiday name cannot be empty!",
								Toast.LENGTH_LONG)
								.show();
						return;
					}
					
					final DateButton startDateButton = ((DateButton) child.findViewById(R.id.btn_select_startDate));
					final long startDate = new GregorianCalendar(startDateButton.getYear(),
							startDateButton.getMonth(),
							startDateButton.getDay()).getTimeInMillis();
					final DateButton endDateButton = ((DateButton) child.findViewById(R.id.btn_select_endDate));
					long endDate = new GregorianCalendar(endDateButton.getYear(),
							endDateButton.getMonth(),
							endDateButton.getDay()).getTimeInMillis();
					if (startDate > endDate) {
						// The start date is greater than the end date
						Toast.makeText(this,
								"A holiday start date is greater than its end date!",
								Toast.LENGTH_LONG)
								.show();
						return;
					}
					// Go to the end of the day
					endDate += 86399999;
					for (final edu.uhcl.csci4838.group3.dto.Holiday holiday : holidays) {
						if (holidayName.equals(holiday.getName())
								&& (startDate == holiday.getStartDate())
								&& (endDate == holiday.getEndDate())) {
							Toast.makeText(this,
									"A duplicate holiday exists!",
									Toast.LENGTH_LONG)
									.show();
							return;
						}
					}
					holidays.add(new edu.uhcl.csci4838.group3.dto.Holiday(holidayName,
							startDate,
							endDate));
				}
			}
			
			// All good
			EditSemesterActivity.dbHelper.addSemester(semesterName);
			for (final edu.uhcl.csci4838.group3.dto.Holiday holiday : holidays) {
				EditSemesterActivity.dbHelper.addHoliday(holiday.getName(),
						semesterName,
						holiday.getStartDate(),
						holiday.getEndDate());
			}
		} else {
			// Edit
			final String semesterName = EditSemesterActivity.inputSemesterName.getText()
					.toString()
					.trim();
			final ContentValues semesterCriteria = new ContentValues(1);
			boolean editSemester = false;
			if (!semesterName.equals(this.semesterCursor.getColName())) {
				// Rename
				if (semesterName.length() == 0) {
					// Empty string
					Toast.makeText(this,
							"The semester name cannot be empty!",
							Toast.LENGTH_LONG)
							.show();
					return;
				}
				
				// Check for existing semester
				semesterCriteria.put(Semester.NAME,
						semesterName);
				final CursorSemester newSemesterCursor = EditSemesterActivity.dbHelper.getSemester(semesterCriteria,
						null,
						true);
				if (newSemesterCursor.getCount() != 0) {
					// The semester name already exists
					Toast.makeText(this,
							"A semester with that name already exists!",
							Toast.LENGTH_LONG)
							.show();
					return;
				}
				newSemesterCursor.close();
				
				editSemester = true;
			}
			
			// Holidays (lots of repeated code to clean up)
			final List<edu.uhcl.csci4838.group3.dto.Holiday> holidays = new ArrayList<edu.uhcl.csci4838.group3.dto.Holiday>(EditSemesterActivity.layoutHolidays.getChildCount());
			for (int i = 0; i < EditSemesterActivity.layoutHolidays.getChildCount(); ++i) {
				final View child = EditSemesterActivity.layoutHolidays.getChildAt(i);
				if (child.getId() == R.id.holidayadd) {
					final String holidayName = ((EditText) child.findViewById(R.id.editText_setHolidayName)).getText()
							.toString()
							.trim();
					if (holidayName.length() == 0) {
						// Empty string
						Toast.makeText(this,
								"A holiday name cannot be empty!",
								Toast.LENGTH_LONG)
								.show();
						return;
					}
					
					final DateButton startDateButton = ((DateButton) child.findViewById(R.id.btn_select_startDate));
					final long startDate = new GregorianCalendar(startDateButton.getYear(),
							startDateButton.getMonth(),
							startDateButton.getDay()).getTimeInMillis();
					final DateButton endDateButton = ((DateButton) child.findViewById(R.id.btn_select_endDate));
					long endDate = new GregorianCalendar(endDateButton.getYear(),
							endDateButton.getMonth(),
							endDateButton.getDay()).getTimeInMillis();
					if (startDate > endDate) {
						// The start date is greater than the end date
						Toast.makeText(this,
								"A holiday start date is greater than its end date!",
								Toast.LENGTH_LONG)
								.show();
						return;
					}
					// Go to the end of the day
					endDate += 86399999;
					for (final edu.uhcl.csci4838.group3.dto.Holiday holiday : holidays) {
						if (holidayName.equals(holiday.getName())
								&& (startDate == holiday.getStartDate())
								&& (endDate == holiday.getEndDate())) {
							Toast.makeText(this,
									"A duplicate holiday exists!",
									Toast.LENGTH_LONG)
									.show();
							return;
						}
					}
					holidays.add(new edu.uhcl.csci4838.group3.dto.Holiday(holidayName,
							startDate,
							endDate,
							((StateRelativeLayout) child).getFieldId()));
					// Only thing that changes from Add (can actually be put in
					// Add)
				}
			}
			
			// All good
			if (editSemester) {
				EditSemesterActivity.dbHelper.editSemester(this.semesterCursor.getColId(),
						semesterCriteria);
			}
			
			// Deleted holidays
			for (final Long id : this.deletedHolidayIds) {
				EditSemesterActivity.dbHelper.deleteHoliday(id.longValue());
			}
			
			// New and edited holidays
			for (final edu.uhcl.csci4838.group3.dto.Holiday holiday : holidays) {
				if (holiday.getId() == -1) {
					// New
					EditSemesterActivity.dbHelper.addHoliday(holiday.getName(),
							semesterName,
							holiday.getStartDate(),
							holiday.getEndDate());
				} else {
					// Edit
					final ContentValues holidayCriteria = new ContentValues(3);
					holidayCriteria.put(Holiday.NAME,
							holiday.getName());
					holidayCriteria.put(Holiday.START_DATE,
							Long.valueOf(holiday.getStartDate()));
					holidayCriteria.put(Holiday.END_DATE,
							Long.valueOf(holiday.getEndDate()));
					EditSemesterActivity.dbHelper.editHoliday(holiday.getId(),
							holidayCriteria);
				}
			}
		}
		this.finish();
	}
	
	/**
	 * XXX
	 * 
	 * @param menu
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(final Menu menu) {
		this.getMenuInflater()
				.inflate(R.menu.options_editsemester,
						menu);
		return true;
	}
	
	/**
	 * XXX
	 * 
	 * @param item
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onOptionsItemSelected(final MenuItem item) {
		switch (item.getItemId()) {
			case R.id.menu_item_delete_semester:
				this.showDeleteSemesterDialog();
				return true;
			case R.id.menu_item_settings:
				this.startActivity(new Intent(this.getApplicationContext(),
						SettingsActivity.class));
				return true;
			case R.id.menu_item_about:
				this.startActivity(new Intent(this.getApplicationContext(),
						AboutActivity.class));
				return true;
			case R.id.menu_item_help:
				this.startActivity(new Intent(this.getApplicationContext(),
						HelpActivity.class));
				return true;
			default:
				Log.wtf("BackpackEDU",
						"Undefined options menu item.");
				return super.onOptionsItemSelected(item);
		}
	}
	
	/**
	 * XXX
	 * 
	 * @param menu
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onPrepareOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onPrepareOptionsMenu(final Menu menu) {
		final MenuItem item = menu.findItem(R.id.menu_item_delete_semester);
		if (item != null) {
			// Don't show 'Delete semester' if we are adding
			if (this.semesterCursor == null) {
				item.setVisible(false);
			} else {
				item.setEnabled(true);
			}
		}
		
		return super.onPrepareOptionsMenu(menu);
	}
	
	/**
	 * XXX
	 * 
	 * @param view
	 *            XXX
	 */
	public void removeHoliday(final View view) {
		final StateRelativeLayout layout = (StateRelativeLayout) view.getParent();
		if (layout.getFieldId() > -1) {
			// This isn't a new holiday
			this.deletedHolidayIds.add(Long.valueOf(layout.getFieldId()));
		}
		((LinearLayout) view.getParent()
				.getParent()).removeView(layout);
	}
	
	/**
	 * XXX
	 * 
	 * @param view
	 *            XXX
	 */
	public void showDateDialog(final View view) {
		final Bundle bundle = new Bundle(1);
		bundle.putParcelable("dateButton",
				((DateButton) view));
		this.showDialog(EditSemesterActivity.DATE_DIALOG_ID,
				bundle);
	}
	
	/**
	 * XXX
	 * 
	 * @param savedInstanceState
	 *            XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.ActivityGroup#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		this.setContentView(R.layout.activity_addedit_semester);
		
		// Get components
		EditSemesterActivity.inputSemesterName = (EditText) this.findViewById(R.id.editText_semesterName);
		EditSemesterActivity.btnAddHoliday = (Button) this.findViewById(R.id.btn_add_holiday);
		EditSemesterActivity.layoutHolidays = (LinearLayout) this.findViewById(R.id.layout_holidays);
		
		// Initialize the deleted list
		this.deletedHolidayIds = new ArrayList<Long>();
		
		// Calling intent
		final Intent callingIntent = this.getIntent();
		final long semesterId = callingIntent.getLongExtra(this.getString(R.string.intent_extra_semesterId),
				-1);
		
		// Start the database helper
		EditSemesterActivity.dbHelper = new BackpackEduDatabaseHelper(this);
		
		// New if -1, or edit if not
		if (semesterId == -1) {
			this.initForAdd();
		} else {
			this.initForEdit(semesterId);
		}
	}
	
	/**
	 * XXX
	 * 
	 * @param id
	 *            XXX
	 * @param args
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreateDialog(int, android.os.Bundle)
	 */
	@Override
	protected Dialog onCreateDialog(final int id,
			final Bundle args) {
		switch (id) {
			case DATE_DIALOG_ID:
				final DateButton dateButton = args.getParcelable("dateButton");
				final Dialog dialog = new DatePickerDialog(this,
						new CustomDateSetListener(dateButton),
						dateButton.getYear(),
						dateButton.getMonth(),
						dateButton.getDay());
				dialog.setOnDismissListener(new OnDismissListener() {
					
					/**
					 * XXX
					 * 
					 * @param dialog
					 *            XXX
					 */
					/* 
					 * (non-Javadoc)
					 * 
					 * @see android.content.DialogInterface.OnDismissListener#onDismiss(android.content.DialogInterface)
					 */
					@Override
					public void onDismiss(final DialogInterface dialog) {
						EditSemesterActivity.this.removeDialog(EditSemesterActivity.DATE_DIALOG_ID);
					}
				});
				return dialog;
			default:
				return null;
		}
	}
	
	/**
	 * XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onDestroy()
	 */
	@Override
	protected void onDestroy() {
		EditSemesterActivity.dbHelper.close();
		super.onDestroy();
	}
	
	/**
	 * XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onRestart()
	 */
	@Override
	protected void onRestart() {
		super.onRestart();
		// TODO Q&D fix to get it working
		if(this.semesterCursor != null) {
			this.semesterCursor.moveToFirst();
		}
	}
	
	/**
	 * XXX
	 */
	private void initForAdd() {
		// Title
		this.setTitle("Add semester");
		
		// Set done button text
		((Button) this.findViewById(R.id.btn_semester_done)).setText("Add");
	}
	
	/**
	 * XXX
	 * 
	 * @param semesterId
	 *            XXX
	 */
	private void initForEdit(final long semesterId) {
		// Cursor
		ContentValues criteria = new ContentValues();
		criteria.put(Semester.ID,
				Long.valueOf(semesterId));
		this.semesterCursor = EditSemesterActivity.dbHelper.getSemester(criteria,
				null,
				true);
		this.startManagingCursor(this.semesterCursor);
		
		// Title
		this.setTitle("Edit semester");
		
		// Set done button text
		((Button) this.findViewById(R.id.btn_semester_done)).setText("Save");
		
		// Populate the fields
		EditSemesterActivity.inputSemesterName.setText(this.semesterCursor.getColName());
		
		// Holidays
		criteria = new ContentValues();
		criteria.put(Holiday.SEMESTER_ID,
				Long.valueOf(semesterId));
		final CursorHoliday holidayCursor = EditSemesterActivity.dbHelper.getHoliday(criteria,
				new String[] { Holiday.START_DATE, Holiday.END_DATE },
				true);
		for (int i = 0; i < holidayCursor.getCount(); ++i) {
			final StateRelativeLayout v = (StateRelativeLayout) this.getLayoutInflater()
					.inflate(R.layout.holidayadd,
							null);
			v.setFieldId(holidayCursor.getColId());
			
			((EditText) v.findViewById(R.id.editText_setHolidayName)).setText(holidayCursor.getColName());
			
			final Calendar startCal = new GregorianCalendar();
			startCal.setTimeInMillis(holidayCursor.getColStartDate());
			final DateButton startDateButton = ((DateButton) v.findViewById(R.id.btn_select_startDate));
			startDateButton.setDay(startCal.get(Calendar.DAY_OF_MONTH));
			startDateButton.setMonth(startCal.get(Calendar.MONTH));
			startDateButton.setYear(startCal.get(Calendar.YEAR));
			
			final Calendar endCal = new GregorianCalendar();
			endCal.setTimeInMillis(holidayCursor.getColEndDate());
			final DateButton endDateButton = ((DateButton) v.findViewById(R.id.btn_select_endDate));
			endDateButton.setDay(endCal.get(Calendar.DAY_OF_MONTH));
			endDateButton.setMonth(endCal.get(Calendar.MONTH));
			endDateButton.setYear(endCal.get(Calendar.YEAR));
			
			EditSemesterActivity.layoutHolidays.addView(v);
			holidayCursor.moveToNext();
		}
		holidayCursor.close();
	}
	
	/**
	 * XXX
	 */
	private void showDeleteSemesterDialog() {
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.menu_title_delete_semester)
				.setMessage("Are you sure you want to delete the semester \""
						+ this.semesterCursor.getColName()
						+ "\" and all of its associated classes?")
				.setPositiveButton("Delete",
						new DialogInterface.OnClickListener() {
							
							@SuppressWarnings("synthetic-access")
							@Override
							public void onClick(final DialogInterface dialog,
									final int which) {
								EditSemesterActivity.dbHelper.deleteSemester(EditSemesterActivity.this.semesterCursor.getColId());
								EditSemesterActivity.this.finish();
							}
						})
				.setNegativeButton(android.R.string.cancel,
						new CancelListener());
		final AlertDialog alert = builder.create();
		alert.show();
	}
	
}
